package com.lizhivscaomei.dueros.tobaccoguider.bot;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baidu.dueros.bot.VideoPlayer;
import com.baidu.dueros.data.request.IntentRequest;
import com.baidu.dueros.data.request.LaunchRequest;
import com.baidu.dueros.data.request.SessionEndedRequest;
import com.baidu.dueros.data.request.audioplayer.event.PlaybackFinishedEvent;
import com.baidu.dueros.data.response.OutputSpeech;
import com.baidu.dueros.data.response.directive.display.RenderTemplate;
import com.baidu.dueros.data.response.directive.display.templates.BodyTemplate1;
import com.baidu.dueros.data.response.directive.display.templates.BodyTemplate4;
import com.baidu.dueros.data.response.directive.display.templates.ImageStructure;
import com.baidu.dueros.data.response.directive.display.templates.TextStructure;
import com.baidu.dueros.data.response.directive.videoplayer.Play;
import com.baidu.dueros.model.Response;
import com.baidu.dueros.nlu.Intent;
import com.google.common.base.Joiner;
import com.lizhivscaomei.dueros.tobaccoguider.entity.Faq;
import com.lizhivscaomei.dueros.tobaccoguider.entity.TobaccoInfo;
import com.lizhivscaomei.dueros.tobaccoguider.mapper.es.TobaccoInfoRepository;
import com.lizhivscaomei.dueros.tobaccoguider.mapper.jpa.FaqMysqlDao;
import com.lizhivscaomei.dueros.tobaccoguider.repo.TobaccoInfoRepo;
import com.lizhivscaomei.dueros.tobaccoguider.repo.TobaccoInfoRepoMysql;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 烟草机器人
 *
 * @author lizhi
 */
@Slf4j
public class TobaccoBot extends VideoPlayer {
    private static final String PRODUCT_BRAND = "tobacco.brand";
    private static final String SYS_NUMBER = "sys.number";
    private static final String PRODUCT_SPEC = "tobacco.spec";
    private static final String COMPANY = "company";
    private static final String SIZE_TYPE = "size.type";
    private static final String APP_NAME = "潍坊烟草现代终端";

    private TobaccoInfoRepository tobaccoInfoRepository;

    private BodyTemplate1 defaultBodyTemplate;

    FaqMysqlDao faqMysqlDao;
    TobaccoInfoRepo tobaccoInfoRepo;

    public TobaccoBot(HttpServletRequest request) throws IOException {
        super(request);
        disableVerify();
        this.tobaccoInfoRepository = SpringUtil.getBean(TobaccoInfoRepository.class);
        this.tobaccoInfoRepo = SpringUtil.getBean(TobaccoInfoRepoMysql.class);
        this.faqMysqlDao = SpringUtil.getBean(FaqMysqlDao.class);

        //构造模板BodyTemplate1
        defaultBodyTemplate = new BodyTemplate1(APP_NAME, TextStructure.TextType.PlainText, APP_NAME);
        defaultBodyTemplate.setBackgroundImageUrl("https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1077883326,1683889725&fm=26&gp=0.jpg");
        defaultBodyTemplate.getTextContent().setPosition(BodyTemplate1.PositionType.TOP_LEFT);
    }

    /**
     * 打开应用回调
     */
    @Override
    protected Response onLaunch(LaunchRequest launchRequest) {
        List<String> welcomeList = new ArrayList<>();
        welcomeList.add("欢迎进入" + APP_NAME + "，我了解各种烟的知识，试试说，介绍一下软中华");
        welcomeList.add("欢迎进入" + APP_NAME);
        welcomeList.add("欢迎进入" + APP_NAME + "，需要我给你推荐烟吗？");
        String content = welcomeList.get((int) (Math.random() * welcomeList.size()));
        this.waitAnswer();
        this.setExpectSpeech(true);
        defaultBodyTemplate.setPlainContent(content);
        RenderTemplate renderTemplate = new RenderTemplate(defaultBodyTemplate);
        this.addDirective(renderTemplate);
        return new Response(new OutputSpeech(OutputSpeech.SpeechType.PlainText, content));
    }

    /**
     * 关闭应用回调
     */
    @Override
    protected Response onSessionEnded(SessionEndedRequest sessionEndedRequest) {
        List<String> byeList = new ArrayList<>();
        byeList.add("欢迎再次使用" + APP_NAME);
        byeList.add("欢迎下次光临");
        String content = byeList.get((int) (Math.random() * 2));
        return new Response(new OutputSpeech(OutputSpeech.SpeechType.PlainText, content));
    }

    /**
     * 意图识别
     */
    @Override
    protected Response onInent(IntentRequest intentRequest) {
        log.info(intentRequest.getIntentName());
        String originalWords = intentRequest.getQuery().getOriginal();
        log.info("用户原话：" + originalWords);
        log.info("识别意图：" + intentRequest.getIntentName());
        //获取关键词
        List<String> keywordList = new ArrayList<>();
        intentRequest.getIntents().get(0).getSlots().forEach((s, slot) -> keywordList.add(slot.getValue()));
        String keywords = Joiner.on(" ").join(keywordList);
        log.info("关键词：" + keywords);
        if (IntentEnum.INTRODUCE.toString().toLowerCase().equals(intentRequest.getIntentName()) || IntentEnum.INTRODUCE2.toString().toLowerCase().equals(intentRequest.getIntentName())) {
            if (CollectionUtils.isNotEmpty(keywordList) && keywordList.size() >= 2) {
                //处理产品简介意图
                return this.dealIntentIntroduce(intentRequest.getIntents().get(0), keywords);
            } else {
                setDelegate();
                this.waitAnswer();
                this.setExpectSpeech(true);
                return new Response(new OutputSpeech(OutputSpeech.SpeechType.PlainText, ""));
            }
        } else if (IntentEnum.SUGGEST.toString().toLowerCase().equals(intentRequest.getIntentName())) {
            //处理香烟推荐（查询）意图
            return this.dealIntentSuggest(intentRequest, intentRequest.getIntents().get(0), keywords);
        } else if (IntentEnum.MYSELF.toString().toLowerCase().equals(intentRequest.getIntentName())) {
            //自我介绍
            return this.introduceMyself(intentRequest);
        } else if (IntentEnum.VIDEO.toString().toLowerCase().equals(intentRequest.getIntentName())) {
            //播放视频
            return this.dealIntentVideo(intentRequest);
        } else if (IntentEnum.SKILL.toString().toLowerCase().equals(intentRequest.getIntentName())) {
            return this.dealIntentSkill(intentRequest);
        } else {
            //处理问答信息
            return this.dealFaqIntentSkill(intentRequest);
        }

    }


    /**
     * 处理香烟简介
     */
    private Response dealIntentIntroduce(Intent intent, String keywords) {
        BodyTemplate4 bodyTemplate = new BodyTemplate4();
        String content = "没找到相关信息";
        TobaccoInfo query = new TobaccoInfo();
        query.setBrand(intent.getSlots().get(PRODUCT_BRAND).getValue());
        query.setSpec(intent.getSlots().get(PRODUCT_SPEC).getValue());
        Optional<TobaccoInfo> detail = this.tobaccoInfoRepo.detail(query);
        if (detail.isPresent()) {
            TobaccoInfo res = detail.get();
            content = res.getContent();
            if (StringUtils.isNotEmpty(res.getFlavor())) {
                content = "口味：" + res.getFlavor() + System.lineSeparator() + "简介：" + content;
            }
            bodyTemplate.setTitle(res.getName());
//            bodyTemplate.setImageUrl("https://sewing.lizhivscaomei.site/image/" + res.getCode() + ".jpg");
            ImageStructure img = new ImageStructure("https://sweing2.lizhivscaomei.site/image/" + res.getCode() + ".jpg", 300, 400);
            bodyTemplate.setImage(img);
        }
        this.waitAnswer();
        this.setExpectSpeech(true);
        bodyTemplate.setPlainContent(content);
        RenderTemplate renderTemplate = new RenderTemplate(bodyTemplate);
        this.addDirective(renderTemplate);
        return new Response(new OutputSpeech(OutputSpeech.SpeechType.PlainText, content));
    }

    /**
     * 处理香烟推荐
     */
    private Response dealIntentSuggest(IntentRequest intentRequest, Intent intent, String keywords) {
        String content = "没有可以推荐的";

        if (StringUtils.isNotEmpty(keywords)) {
            TobaccoInfo query = new TobaccoInfo();
            if (null != intent.getSlots().get(COMPANY)) {
                query.setCompany(intent.getSlots().get(COMPANY).getValue());
            }
            if (null != intent.getSlots().get(SIZE_TYPE)) {
                query.setSizeType(intent.getSlots().get(SIZE_TYPE).getValue());
            }
            if (null != intent.getSlots().get(PRODUCT_BRAND)) {
                query.setBrand(intent.getSlots().get(PRODUCT_BRAND).getValue());
            }
            if (null != intent.getSlots().get(SYS_NUMBER)) {
                query.setSmallSalePrice(Integer.parseInt(intent.getSlots().get(SYS_NUMBER).getValue()));

            }
            List<TobaccoInfo> detailList = this.tobaccoInfoRepo.list(query);
            if (CollectionUtil.isNotEmpty(detailList)) {
                content = "共找到" + detailList.size() + "款香烟：\n";
                List<String> nameList = detailList.stream().map(item -> item.getName() + "。").collect(Collectors.toList());
                content = content + StringUtils.join(nameList, System.lineSeparator());
            }
            defaultBodyTemplate.setTitle("香烟推荐");
            defaultBodyTemplate.setPlainContent(content);
            defaultBodyTemplate.setBackgroundImageUrl("");
            RenderTemplate renderTemplate = new RenderTemplate(defaultBodyTemplate);
            this.addDirective(renderTemplate);
        } else {
            int test = (int) (Math.random() * 3);
            log.info(test + "");
            switch (test) {
                case 1: {
                    content = "需要什么价位的烟？";
                    ask(SYS_NUMBER);
                    break;
                }
                case 2: {
                    content = "需要什么品牌的烟？";
                    ask(PRODUCT_BRAND);
                    break;
                }
                default: {
                    content = "需要什么尺寸规格的烟？";
                    ask(SIZE_TYPE);
                    break;
                }
            }
        }
        this.waitAnswer();
        this.setExpectSpeech(true);
        return new Response(new OutputSpeech(OutputSpeech.SpeechType.PlainText, content));
    }

    /**
     * 打开应用回调
     */
    private Response introduceMyself(IntentRequest request) {
        String content = "你好，我是潍坊烟草小度！我有以下技能：" +
                "1.根据品牌、型号、价格、尺寸给你推荐烟，试着说一下，推荐个二十块钱左右的烟？" +
                "2.详细介绍烟的信息，试着说一下，介绍一下软中华";
        this.waitAnswer();
        this.setExpectSpeech(true);
        defaultBodyTemplate.setPlainContent(content);
        RenderTemplate renderTemplate = new RenderTemplate(defaultBodyTemplate);
        this.addDirective(renderTemplate);
        return new Response(new OutputSpeech(OutputSpeech.SpeechType.PlainText, content));
    }

    /**
     * 播放视频
     */
    private Response dealIntentVideo(IntentRequest request) {
        // 新建视频播放指令
        Play play = new Play("https://vd4.bdstatic.com/mda-mc3g1acpzcyn4ym4/sc/mda-mc3g1acpzcyn4ym4.mp4?v_from_s=hba_videoui_4135&auth_key=1614830204-0-0-794a7beb25717ca4455719a52e5e23a0&bcevod_channel=searchbox_feed&pd=1&pt=3&abtest=8_1");
        play.setPlayBehavior(Play.PlayBehaviorType.REPLACE_ALL);
        this.addDirective(play);
        return new Response(new OutputSpeech(OutputSpeech.SpeechType.PlainText, ""));
    }

    @Override
    protected Response onPlaybackFinishedEvent(PlaybackFinishedEvent playbackFinishedEvent) {
        this.waitAnswer();
        this.setExpectSpeech(true);
        return super.onPlaybackFinishedEvent(playbackFinishedEvent);
    }

    /**
     * 处理存烟技巧
     */
    private Response dealIntentSkill(IntentRequest request) {
        String content = "烟草公司和卷烟厂成品仓库对卷烟的堆码方式、温湿度等都有严格的要求，也有相应的设备来保障，确保成品卷烟质量的安全。 而作为零售客户存放卷烟，没有相应的条件，该如何存放卷烟呢？\n" +
                "卷烟存放最怕的是潮湿、暴晒，因此卷烟的存放应注意通风、防晒、防潮、除湿。\n" +
                "一、通风措施\n" +
                "1.卷烟柜台尽量不要紧贴墙壁，有效避开来自墙面的潮气；\n" +
                "2.将卷烟放在相对较高的货架上（比如10～15厘米高）和阴凉、干燥、通风的地方；\n" +
                "3.卷烟整条堆垛存放时可采用“井”字形、三角形等，增加空气流通；\n" +
                "4、充分利用店内空调、风扇等设施，保持店内通风。\n" +
                "二、防晒措施\n" +
                " 可根据季节变化调整卷烟摆放位置，或为烟柜顶部安装遮阳篷布、使用空烟盒陈列，避免因阳光直接暴晒而造成卷烟外包装变形、变色、霉变。\n" +
                "三、防潮措施\n" +
                "1.把卷烟和地面之间放上些防潮的物品,如纸皮、泡沫板等，或者把存放卷烟的纸箱放在架子上，不给卷烟和地面直接接触的机会，增加卷烟存放的安全度；\n" +
                "     2.把防雨毡垫在烟箱下面，能有效隔绝来自地面的潮气；内外有油漆涂层的铁柜在多雨季节不易返潮，因此可用此类铁柜储存卷烟；\n" +
                "     3.将卷烟的存放应远离厨房、卫生间等有水源的地方，不与饮料及其他含水分大、有异味的物品混放。\n" +
                "四、除湿措施\n" +
                "1.店内应充分发挥空调、除湿机等设备的防潮防湿功能；\n" +
                " 2.可将生石灰铺撒于地面用于保温除湿；\n" +
                " 3.同时可以用一些除湿剂放在存放香烟的铁箱或纸盒中，或是在货架、货柜内放置干燥剂、吸附能力较强的活性炭包，但在这个过程中，要注意的及时更换除湿剂、活性炭，除湿效果较为明显。\n";
        this.waitAnswer();
        this.setExpectSpeech(true);
        defaultBodyTemplate.setPlainContent(content);
        defaultBodyTemplate.setBackgroundImageUrl("");
        RenderTemplate renderTemplate = new RenderTemplate(defaultBodyTemplate);
        this.addDirective(renderTemplate);
        return new Response(new OutputSpeech(OutputSpeech.SpeechType.PlainText, content));
    }

    /**
     * 问答题
     */
    private Response dealFaqIntentSkill(IntentRequest request) {
        String content = "我没有听清，能再说一遍吗";
        if(CollectionUtil.isNotEmpty(request.getIntents())){
            Optional<Faq> faqOptional = this.faqMysqlDao.findById(request.getIntents().get(0).getName());
            if (faqOptional.isPresent()) {
                content = faqOptional.get().getAnswer();
            }
        }
        this.waitAnswer();
        this.setExpectSpeech(true);
        defaultBodyTemplate.setPlainContent(content);
        defaultBodyTemplate.setBackgroundImageUrl("");
        RenderTemplate renderTemplate = new RenderTemplate(defaultBodyTemplate);
        this.addDirective(renderTemplate);
        return new Response(new OutputSpeech(OutputSpeech.SpeechType.PlainText, content));
    }
}
